import type { BamlRuntime, BamlCtxManager, ClientRegistry, Image, Audio, Pdf, Video } from "@boundaryml/baml"
import { toBamlError, HTTPRequest } from "@boundaryml/baml"
import type { Checked, Check } from "./types"
import type * as types from "./types"
import type {
  {%- for t in types %}{{ t }}{% if !loop.last %}, {% endif %}{% endfor -%}
} from "./types"
import type TypeBuilder from "./type_builder"
import type * as events from "./events"

type BamlCallOptions<EventsT = never> = {
  tb?: TypeBuilder
  clientRegistry?: ClientRegistry
  env?: Record<string, string | undefined>
  events?: EventsT
}

export class HttpRequest {
  constructor(private runtime: BamlRuntime, private ctxManager: BamlCtxManager) {}

  {% for func in functions %}
  {{ func.name }}(
      {% for (name, arg_type) in func.args -%}
      {{name}}{% if arg_type.meta().is_optional() %}?{% endif %}: {{arg_type.serialize_type(pkg)}},
      {%- endfor %}
      __baml_options__?: BamlCallOptions<{{ func.event_type_param() }}>
  ): HTTPRequest {
    try {
      const rawEnv = __baml_options__?.env ? { ...process.env, ...__baml_options__.env } : { ...process.env };
      const env: Record<string, string> = Object.fromEntries(
        Object.entries(rawEnv).filter(([_, value]) => value !== undefined) as [string, string][]
      );
      return this.runtime.buildRequestSync(
        "{{func.name}}",
        {
          {% for (name, arg_type) in func.args -%}
          "{{name}}": {{name}}{% if arg_type.meta().is_optional() %}?? null{% endif %}{% if !loop.last %},{% endif %}
          {%- endfor %}
        },
        this.ctxManager.cloneContext(),
        __baml_options__?.tb?.__tb(),
        __baml_options__?.clientRegistry,
        false,
        env,
      )
    } catch (error) {
      throw toBamlError(error);
    }
  }
  {% endfor %}
}

export class HttpStreamRequest {
  constructor(private runtime: BamlRuntime, private ctxManager: BamlCtxManager) {}

  {% for func in functions %}
  {{ func.name }}(
      {% for (name, arg_type) in func.args -%}
      {{name}}{% if arg_type.meta().is_optional() %}?{% endif %}: {{arg_type.serialize_type(pkg)}},
      {%- endfor %}
      __baml_options__?: BamlCallOptions<{{ func.event_type_param() }}>
  ): HTTPRequest {
    try {
      const rawEnv = __baml_options__?.env ? { ...process.env, ...__baml_options__.env } : { ...process.env };
      const env: Record<string, string> = Object.fromEntries(
        Object.entries(rawEnv).filter(([_, value]) => value !== undefined) as [string, string][]
      );
      return this.runtime.buildRequestSync(
        "{{func.name}}",
        {
          {% for (name, arg_type) in func.args -%}
          "{{name}}": {{name}}{% if arg_type.meta().is_optional() %}?? null{% endif %}{% if !loop.last %},{% endif %}
          {%- endfor %}
        },
        this.ctxManager.cloneContext(),
        __baml_options__?.tb?.__tb(),
        __baml_options__?.clientRegistry,
        true,
        env,
      )
    } catch (error) {
      throw toBamlError(error);
    }
  }
  {% endfor %}
}
